
"""
    pyprosim - a simple prolog compiler developed to PCS2056 course (Compilers) at Poli-USP\
    Copyright (C) 2008 Rodrigo Rodrigues da Silva

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
"""

from pyprosim.token import *
from pycoopiler.enum import enum
from pyprosim.submaquina import submaquina
from pyprosim.maq_dado import maq_dado
from pyprosim.maq_lclausula import maq_lclausula
from pyprosim.maq_args import maq_args
import logging

class maq_programa(submaquina):
    
    states = enum("  _0_ABRE_P \
                     _1_NOME \
                     _2_VINCULO \
                     _3_DADO \
                     _4_FECHA_P \
                     _5_ABRE_P \
                     _6_NOME \
                     _7_VINCULO_OU_INF \
                     _8_VINCULO \
                     _9_ABRE_P_OU_DADO \
                     _10_LCLAUSULA \
                     _11_FECHA_P \
                     _12_FECHA_P \
                     _13_ABRE_P \
                     _14_META_OU_NOME \
                     _15_ARGS \
                     _16_NOME \
                     _17_DADO \
                     _18_FECHA_P \
                     _19_FIM")
    
    def __init__(self, _tkzr):
        self.tkzr = _tkzr 
        self.state = self.states._0_ABRE_P
        self.log_chamada("PROGRAMA")
        #self.current = self.tkzr.next_token()
        self.current = self.tkzr.current

    def analyze(self):
                
        while not self.state == self.states._19_FIM:            
            self.log_state()
            
            if self.state == self.states._0_ABRE_P: 
                if self.current.type == self.current.types.ABRE_P:
                    self.state = self.states._1_NOME              
                else: raise Exception ("Erro Sintatico! Esperando ABRE_P")
                self.consume()  
            
            elif self.state == self.states._1_NOME:
                if self.current.type == self.current.types.NOME:
                    self.state = self.states._2_VINCULO              
                else: raise Exception ("Erro Sintatico! Esperando NOME")
                self.consume()
                
            elif self.state == self.states._2_VINCULO:
                if self.current.type == self.current.types.VINCULO:
                    self.state = self.states._3_DADO              
                else: raise Exception ("Erro Sintatico! Esperando VINCULO")
                self.consume()
                
            elif self.state == self.states._3_DADO:
                md = maq_dado(self.tkzr)
                md.analyze()
                self.current = self.tkzr.current
                self.state = self.states._4_FECHA_P
                
            elif self.state == self.states._4_FECHA_P:
                if self.current.type == self.current.types.FECHA_P:
                    self.state = self.states._5_ABRE_P             
                else: raise Exception ("Erro Sintatico! Esperando FECHA_P")
                self.consume()
                
            elif self.state == self.states._5_ABRE_P:
                if self.current.type == self.current.types.ABRE_P:
                    self.state = self.states._6_NOME           
                else: raise Exception ("Erro Sintatico! Esperando ABRE_P")
                self.consume()
                
            elif self.state == self.states._6_NOME:
                if self.current.type == self.current.types.NOME:
                    self.state = self.states._7_VINCULO_OU_INF          
                else: raise Exception ("Erro Sintatico! Esperando NOME")
                self.consume()
                
            elif self.state == self.states._7_VINCULO_OU_INF:
                if self.current.type == self.current.types.VINCULO:
                    self.state = self.states._3_DADO 
                elif self.current.type == self.current.types.INF:
                    self.state = self.states._8_VINCULO           
                else: raise Exception ("Erro Sintatico! Esperando VINCULO ou INF")
                self.consume()
                
            elif self.state == self.states._8_VINCULO:
                if self.current.type == self.current.types.VINCULO:
                    self.state = self.states._9_ABRE_P_OU_DADO       
                else: raise Exception ("Erro Sintatico! Esperando VINCULO")
                self.consume()
                
            elif self.state == self.states._9_ABRE_P_OU_DADO:
                if self.current.type == self.current.types.ABRE_P:
                    self.state = self.states._10_LCLAUSULA
                    self.consume()
                else:
                    md = maq_dado(self.tkzr)
                    md.analyze()
                    self.current = self.tkzr.current
                    self.state = self.states._12_FECHA_P                
                
            elif self.state == self.states._10_LCLAUSULA:
                ml = maq_lclausula(self.tkzr)
                ml.analyze()                
                self.current = self.tkzr.current
                self.state = self.states._11_FECHA_P
                
            elif self.state == self.states._11_FECHA_P:
                if self.current.type == self.current.types.FECHA_P:
                    self.state = self.states._12_FECHA_P             
                else: raise Exception ("Erro Sintatico! Esperando FECHA_P")
                self.consume()
                
            elif self.state == self.states._12_FECHA_P:
                if self.current.type == self.current.types.FECHA_P:
                    self.state = self.states._13_ABRE_P        
                else: raise Exception ("Erro Sintatico! Esperando FECHA_P")
                self.consume()
                
            elif self.state == self.states._13_ABRE_P:
                if self.current.type == self.current.types.ABRE_P:
                    self.state = self.states._14_META_OU_NOME          
                else: raise Exception ("Erro Sintatico! Esperando ABRE_P")
                self.consume()
                
            elif self.state == self.states._14_META_OU_NOME:
                if self.current.type == self.current.types.META:
                    self.state = self.states._16_NOME 
                elif self.current.type == self.current.types.NOME:
                    self.state = self.states._15_ARGS           
                else: raise Exception ("Erro Sintatico! Esperando NOME ou META")
                self.consume()
                
            elif self.state == self.states._15_ARGS:
                ma = maq_args(self.tkzr)
                ma.analyze()                
                self.current = self.tkzr.current
                self.state = self.states._8_VINCULO
                
            elif self.state == self.states._16_NOME:
                if self.current.type == self.current.types.NOME:
                    self.state = self.states._17_DADO          
                else: raise Exception ("Erro Sintatico! Esperando NOME")
                self.consume()
                
            elif self.state == self.states._17_DADO:
                md = maq_dado(self.tkzr)
                md.analyze()                
                self.current = self.tkzr.current
                self.state = self.states._18_FECHA_P
                
            elif self.state == self.states._18_FECHA_P:
                if self.current.type == self.current.types.FECHA_P:
                    self.state = self.states._19_FIM
                else: raise Exception ("Erro Sintatico! Esperando FECHA_P")
                self.consume()
            
            else: raise Exception("ERRO: Estado invalido: " + self.state)
        self.log_retorno("PROGRAMA")